home *** CD-ROM | disk | FTP | other *** search
/ stazsoftware.com / www.stazsoftware.com.tar / www.stazsoftware.com / futurebasic / sample-code / DBFD.sit / DBFD2.0 / DataBrowser With Toolbox / Simple DataBrowser < prev    next >
Text File  |  2003-11-13  |  30KB  |  897 lines

  1.  
  2. '~'A
  3. '                       Runtime : Rntm Appearance.Incl
  4. '                           CPU : Carbon
  5. '                    CALL Req'd : Off
  6. '~'B
  7. '~Introduction
  8. /*
  9.  
  10.      Simple DataBrowser demo is meant to give the basis for using and
  11.      exploring the rich Carbon DataBrowser control.
  12.  
  13.      The demo will let the end-user select a folder and then will display
  14.      its content in a DataBrowser control. Files and folders will be listed
  15.      along with their icon.
  16.  
  17.      A DataBrowser is a Carbon control with which you will have a love or
  18.      hate affair (depending on your success in mastering it); well, let's say
  19.      the Apple documentation is a bit demanding on the topic.
  20.  
  21.      The DataBrowser is in itself a whole universe that certainly requires
  22.      some time for the discovery. Anyway, if you're new to the thing, here
  23.      is what you need to know to get you started. Be prepared to be amazed.
  24.  
  25.      The purpose of a DataBrowser control is to help in the navigation
  26.      through information displayed in list view or column view. It also
  27.      allows the end-user to edit that information. This particular control
  28.      has a whole lot of features that can be implemented gradually:
  29.  
  30.        Ñ No limitation on the number of cells displayed in a list,
  31.        Ñ Built-in drag-and-drop handling,
  32.        Ñ Built-in display types for text, icons, checkboxes, pop-up menus,
  33.          progress bars, relevance ranks, and sliders,
  34.        Ñ Support for contextual menus and context-sensitive help
  35.        Ñ Built-in text editing for cells displaying text, and
  36.        Ñ Built-in hierarchical list support.
  37.  
  38.      The DataBrowser communicates with your program via a set of callback
  39.      procedures, but to get the control to function, only one callback is
  40.      mandatory. It is called with the barbaric name GetSetItemDataProc
  41.      because the DataBrowser uses the same routine to request information
  42.      about the data it must display or to inform your program that the
  43.      end-user has modified an editable cell in the table. In the demo below
  44.      we will not deal with user changes, we will just display information.
  45.  
  46.      The steps to put the pieces together are the following:
  47.  
  48.        Ñ Create a DataBrowser control in a window
  49.        Ñ Install the callback procedures in the DataBrowser
  50.        Ñ Configure the DataBrowser (adding columns)
  51.        Ñ Add items in the DataBrowser (adding rows)
  52.        Ñ Chat with the DataBrowser (displaying cells)
  53.  
  54.      This slightly differs from the creation of a button with the
  55.      APPEARANCE BUTTON statement, but actually it is not much harder.
  56.  
  57.      Please use the popup menu button FN at the top left of this window
  58.      and check the Unsorted item because I will refer to functions used
  59.      in the demo that follows.
  60.  
  61.      The demo starts calling FN StartProgram which intalls a basic menu,
  62.      opens a window, creates a DataBrowser control and enters the main
  63.      event loop waiting for a menu choice.
  64.  
  65. '~Creating a DataBrowser Control
  66.  
  67.      The creation of the DataBrowser is extremely simple and realized with
  68.      a single call to a Toolbox function:
  69.  
  70.      err = FN CreateDataBrowserControl( windowRef, bounds, _kDataBrowserListView, browser )
  71.      
  72.      On return the browser variable will be set with the Control Reference
  73.      for the DataBrowser freshly created.
  74.  
  75. '~Installing the callback procedures
  76.  
  77.      Installing the callback procedures is somewhat a bit more complicated,
  78.      but not that hard. You need first a record variable of the
  79.      DataBrowserCallbacks type which contains 10 different fields, each one
  80.      dedicated to a routine that will handle a specific task. You must first
  81.      initialize the callbacks for your variable with a Toolbox function like
  82.      so:
  83.  
  84.      err = FN InitDataBrowserCallbacks( myDataBrowserCallbacks )
  85.  
  86.      then, you set the appropriate fields of the record variable with your
  87.      procedures that the DataBrowser will use to communicate with your program.
  88.      Finally, you can install the callbacks in the DataBrowser like so:
  89.  
  90.      err = FN SetDataBrowserCallbacks( browser, myDataBrowserCallbacks )
  91.  
  92.      Here in the demo, we will use only one field to install the mandatory
  93.      procedure (see how it is done in local fn InstallDataBrowserCallbacks)
  94.  
  95.  
  96. '~Adding columns
  97.      
  98.      Once you have successfully created the DataBrowser control and installed
  99.      the callbacks, you can setup the columns you want to display. In this demo,
  100.      this is done at the LOCAL FN ConfigureDataBrowser. Since it is a bit
  101.      cumbersome, but not difficult, to define a column, I have created two little
  102.      functions to simplify the coding when you have a lot of columns to add.
  103.      You must define all the column properties (including a unique identifier
  104.      with which you can refer to that column later) and set also the style of its
  105.      header. This is merely done setting the fields of an appropriate variable
  106.      of type DataBrowserListViewColumnDesc before calling a Toolbox function
  107.      like so:
  108.  
  109.      err = FN AddDataBrowserListViewColumn( browser, columnDescriptor, _kDataBrowserListViewAppendColumn )
  110.  
  111.      Note: the _kDataBrowserListViewAppendColumn constant is just a big number
  112.      to make sure that the added column is appended and not inserted between
  113.      two other columns.
  114.  
  115. '~Adding rows
  116.  
  117.      Adding row is actually adding items in the list maintained by the DataBrowser
  118.      control. The added items are identifiers of type DataBrowserItemID (defined
  119.      as an unsigned long integer). This is done in the demo below at the LOCAL FN
  120.      AddOrClearDataBrowserItems, because the program is very simple and it needs
  121.      only to add or delete all the items at once. Again, you use a specific
  122.      Toolbox function like the following:
  123.  
  124.      err = FN AddDataBrowserItems( browser, 0, 1, itemID, 0 )
  125.  
  126.      To add multiple items at once:
  127.  
  128.      err = FN AddDataBrowserItems( browser, 0, numberOfItems, @arrayOfItemID(0), 0 )
  129.  
  130.      Removing items is equally simple:
  131.  
  132.      err = fn RemoveDataBrowserItems ( browser, 0, numberOfItems, @arrayOfItems(0) , 0 )
  133.  
  134.      Note: in the demo below, we use predefined constants, namely _kDataBrowserNoItem
  135.      and _kDataBrowserItemNoProperty which both have the value 0.
  136.  
  137. '~Displaying cells
  138.  
  139.      Now you're almost ready to see your items on screen. But you need to know
  140.      that the DataBrowser control will call the GetSetItemData procedure when
  141.      it needs to display the info regarding an item, so that it can show
  142.      the appropriate values in the cells of the table. In the demo below the
  143.      entry point of the callback procedure is located at the end of the source
  144.      code, but the procedure calls immediately the local function MyGetSetItemData,
  145.      passing back the values it has received, so the actual work is done there.
  146.  
  147.      When the DataBrowser invokes your callback procedure it passes to your
  148.      program a few parameters that tell what's going on. They tell you
  149.      which DataBrowser is making the call, which itemID is concerned, which
  150.      property is involved (let's say the column to simplify), a pointer to the
  151.      data in the cell and finally a boolean value that indicates if the
  152.      DataBrowser is making the call because it requests information from your
  153.      program, or because it informs your program that the end-user of the
  154.      application has changed the cell's contents and that it is time for you to
  155.      accept or refuse the change. In the demo below, we will just answer the
  156.      DataBrowser when it calls the program for the information it needs to
  157.      display.
  158.      The information you must give back to the DataBrowser depends on the
  159.      column property, that is to say the type of data it must display in the
  160.      cell. For example, if the cell displays a checkbox to represent the info,
  161.      your program must send back a value to tell the DataBrowser if the button
  162.      must be checked or unchecked for the concerned item.
  163.      For each content type there is a specific call. In the case of a checkbox
  164.      you would use a ThemeButtonValue (i.e. _kThemeButtonOff, _kThemeButtonOn
  165.      or _kThemeButtonMixed ) along with the appropriate function:
  166.      
  167. // for checkbox
  168.      err = fn SetDataBrowserItemDataButtonValue( itemData, ThemeButtonValue )
  169. // for text
  170.      err = fn SetDataBrowserItemDataText( itemData, CFStringRef )
  171. // for icon
  172.      err = fn SetDataBrowserItemDataIcon( itemData, IconRef )
  173. // for popup menu
  174.      err = fn SetDataBrowserItemDataMenuRef( itemData, MenuRef )
  175. // for slider, relevance rank, progress bar, popup menuItem
  176.      err = fn SetDataBrowserItemDataValue( itemData, LongIntegerValue )
  177. // for date and time
  178.      err = fn SetDataBrowserItemDataLongDateTime( itemData, LongDateTime )
  179.  
  180.      There is way much more things to know about the DataBrowser control, 
  181.      and I have not yet mentioned that the control can be customized, 
  182.      in fact, there's no less than a total of 17 callback procedures that 
  183.      you could install in the control, so the possibilities are endless,
  184.      but now you can start to play with it when the principles are understood.
  185.      
  186.  
  187.                                                       Alain   May 2003
  188. */
  189. '~'6
  190.  
  191. /*
  192.      Converted Apple header file for DataBrowser declarations
  193. */
  194. Include "Tlbx ControlDefinitions.Incl"
  195.  
  196. /*
  197.      We will use some functions located in those headers
  198. */
  199. Include "Util_Files.incl"
  200. Include "Tlbx Icons.Incl"
  201.  
  202. '~Toolbox Added Declarations
  203. /*
  204.      Missing Toolbox declarations from the FB header files
  205. */
  206. _kWindowInWindowMenuAttribute  = (1 << 27 )
  207. _kControlDataBrowserPart       = 24
  208.  
  209. Toolbox Fn SetAutomaticControlDragTrackingEnabledForWindow( WindowRef inWindow, Boolean inTracks) = OSStatus
  210. Toolbox Fn CFAllocatorGetDefault = CFAllocatorRef
  211.  
  212. '~Application Constants
  213.  
  214. // window FB identifier
  215. _mainWnd         = 1
  216.  
  217. // custom creator code and identifier for the BrowserData control
  218. _myCreator       = _"DEMO"
  219. _myDataBrowser   = _"Brsr"// 
  220.  
  221. // custom identifier of the unique column we will use in the demo
  222. _fileColumnID    = _"file"
  223.  
  224. _scrollBarWidth  = 16
  225.  
  226. // elementary menu identifiers
  227. _menuFile = 1
  228.  
  229. Begin Enum 1
  230. _itemOpenFolder
  231. _
  232. _itemQuit
  233. End Enum
  234.  
  235. // to use with the AddOrClearDataBrowser FN
  236. Begin Enum
  237. _addItems
  238. _clearItems
  239. End Enum
  240.  
  241. '~Application Globals
  242. /*
  243.      Define a custom record holding the item information
  244.      we are interested in. The itemID field will help us
  245.      to synchronize with the list maintained by the DataBrowser.
  246.      We will store the file items in a dynamic array of that
  247.      type of record. In that demo, we could have used the index
  248.      in the array as the itemID for the items.
  249.  
  250.      We will only display the name and the file icon,
  251.      therefore only the spec field and the file type
  252.      are required in the demo. The other fields are
  253.      left here so that you could start playing adding
  254.      columns.
  255. */
  256. Begin Record ItemRecord
  257. Dim itemID   As Long
  258. Dim spec     As FSSpec   
  259. Dim type     As OSType
  260. Dim creator  As OSType
  261. Dim dataLen  As Long
  262. Dim rsrcLen  As Long
  263. Dim cDate    As Long
  264. Dim mDate    As Long
  265. Dim flags    As Short
  266. Dim attrib   As Short
  267. End Record
  268.  
  269. Begin Globals
  270.  
  271. Dim Dynamic       gFiles(_maxInt) As ItemRecord
  272.  
  273. End Globals
  274.  
  275. '~';
  276. '~-
  277. '~Utility Functions
  278. /*
  279.      Handy function that returns the maximum index in a dynamic array
  280. */
  281. Def Fn UBound(@P As Ptr) = [P + _AutoXREFCurr] - 1
  282.  
  283. '~'1
  284. /*
  285.      This function returns the iconRef for a given file
  286. */
  287. Clear Local Mode
  288. Local Fn GetFileIcon( fSpec As .FSSpec, type As OSType )
  289. '~'9
  290. Dim @ iconH As IconRef
  291. Dim @ label As Int
  292. Dim   err   As OSErr
  293.  
  294. If fSpec Then err = Fn GetIconRefFromFile( #fSpec, iconH, label )
  295. Long If err != _noErr Or iconH = _nil
  296. Select type
  297. Case _"APPL" : type = _kGenericApplicationIcon
  298. Case _"fldr" : type = _kGenericFolderIcon
  299. Case Else    : type = _kGenericDocumentIcon
  300. End Select
  301. err = Fn GetIconRef( _kOnAppropriateDisk, _kSystemIconsCreator, type, iconH )
  302. End If
  303.  
  304. End Fn = iconH
  305.  
  306.  
  307. '~--
  308. '~Application Functions
  309.  
  310. '~'1
  311. /*
  312.      This function retrieves the browser reference from the window
  313.      in which it is located.
  314.      The browser reference has been saved has a window property.
  315.      You can store private properties with user interface elements
  316.      as your liking and retrieve them when you need them.
  317. */
  318. Clear Local
  319. Local Fn GetDataBrowserFromWindow( wRef As WindowRef )
  320. '~'9
  321.  
  322. Dim As OSStatus     err
  323. Dim As ControlRef @ browser
  324.  
  325. Long If wRef
  326. err = Fn GetWindowProperty( wRef, _myCreator, _myDataBrowser, Sizeof(browser), #_nil, browser )
  327. End If
  328.  
  329. End Fn = browser
  330.  
  331.  
  332. '~'1
  333. /*
  334.      This function scans the folder specified by its FSSpec,
  335.      and stores the item information found in our global
  336.      dynamic array.
  337. */
  338. Clear Local Fn CollectFileItems ( fSpec As .FSSpec )
  339. '~'9
  340.  
  341. Dim As Short  Index
  342. Dim           pb.128
  343.  
  344. #If Ndef _kFolderBit
  345. _kFolderBit = 3
  346. #Endif
  347.  
  348. Index = 1// start at index 1
  349.  
  350. Do
  351.  
  352. pb.ioFDirIndex%  = Index// fill the param block
  353. pb.ioNamePtr&    = @fSpec.name// the folder requested
  354. pb.ioVRefNum%    = fSpec.vRefNum
  355. pb.ioDirID&      = fSpec.parID
  356.  
  357. If Fn PBGetCatInfoSync( pb ) Then Exit Do// get info on item and leave the loop on error
  358.  
  359. Long If ( pb.ioFlUsrWds.fdFlags% And _fInvisible ) = _false// skip invisible items
  360. gFiles.itemID(Index) = Index// this index will become our DataBrowser itemID
  361. gFiles.spec  (Index) = fSpec// save the item FSSpec
  362.  
  363. Long If Fn BitTst (pb.ioFlAttrib%, _kFolderBit)// Is it a folder?
  364.  // it's a folder...
  365. gFiles.type   (Index)  = _"fldr"// set the file type
  366. gFiles.creator(Index)  = _"----"// set the creator code
  367.  
  368. Xelse// it is a file...
  369.  
  370. gFiles.type   (Index) = pb.ioFlUsrWds.fdType&// grab the info from the param block
  371. gFiles.creator(Index) = pb.ioFlUsrWds.fdCreator&
  372. gFiles.flags  (Index) = pb.ioFlUsrWds.fdFlags%
  373. gFiles.dataLen(Index) = pb.ioFlLgLen&
  374. gFiles.rsrcLen(Index) = pb.ioFlRLgLen&
  375. gFiles.cDate  (Index) = pb.ioFlCrDat&
  376. gFiles.mDate  (Index) = pb.ioFlMdDat&
  377. gFiles.attrib (Index) = pb.ioFlAttrib%
  378. End If
  379.  
  380. End If
  381.  
  382. index++// next file or folder in the current folder
  383.  
  384. Until _nil
  385.  
  386. End Fn
  387.  
  388.  
  389.  
  390. '~-----
  391. '~DataBrowser Setting & Getting Data
  392. '~'1
  393. /*
  394.      This function is called via a callback procedure. This is
  395.      the only required routine to work with a DataBrowser control.
  396.      The DataBrowser asks you to setup some values for the cells
  397.      that it must display. Those values are set with specific functions
  398.      depending on the type of the cell to be updated.
  399.      With the same callback routine the DataBrowser may inform your
  400.      program that a cell has been changed by the end user, so it is
  401.      time to get the value sent by the DataBrowser to update your
  402.      internal information.
  403. */
  404. Clear Local Fn MyGetSetItemData( browser As ControlRef, itemID As DataBrowserItemID, columnPropID As DataBrowserPropertyID, itemData As DataBrowserItemDataRef, userChangedItemData As Boolean )
  405. '~'9
  406. Dim As OSStatus    err
  407. Dim As CFStringRef txt
  408. Dim As IconRef     iconH
  409. Dim As FSSpec      fSpec : fSpec = gFiles.spec(itemID)// copy info from the dynamic array...
  410. Dim As OSType      fType : fType = gFiles.type(itemID)// ... in local variables
  411.  
  412. err = _noErr
  413.  
  414. Long If userChangedItemData = _false
  415.  
  416. Select columnPropID// Which property has been requested by the DataBrowser
  417.  
  418. Case _fileColumnID' Names and icons for our unique column
  419.  
  420. iconH = Fn GetFileIcon( fSpec, ftype )// Retrieve the icon file
  421. Long If iconH// and give back the IconRef to the DataBrowser
  422. err = Fn SetDataBrowserItemDataIcon( itemData, iconH )
  423. err = Fn ReleaseIconRef(iconH)
  424. End If
  425. // Create a CFSStringRef with the item filename and give it back to the DataBrowser
  426. txt = Fn CFStringCreateWithPascalString( Fn CFAllocatorGetDefault, fSpec.name, _kCFStringEncodingMacRoman )
  427. err = Fn SetDataBrowserItemDataText( itemData, txt ) : CFRelease( txt )
  428.  
  429. Case Else:
  430.  
  431. err = _errDataBrowserPropertyNotSupported
  432.  
  433. End Select
  434.  
  435. Xelse
  436. /*
  437.      The end user has altered the cell if we come here.
  438. */
  439. err = _errDataBrowserPropertyNotSupported
  440.  
  441. End If
  442.  
  443. End Fn = err
  444.  
  445.  
  446. /*
  447.      This function is called to add or delete all the
  448.      items in the DataBrowser control.
  449. */
  450. Clear Local
  451. Local Fn AddOrClearDataBrowserItems( whatToDo )
  452. '~'9
  453. Dim As ControlRef   browser
  454. Dim As UInt32       i, @ tempItem, numberOfItems
  455. Dim As OSStatus     err
  456. Dim As Handle       itemsHandle
  457. /*
  458.      Get the browser reference from the window
  459. */
  460. browser = Fn GetDataBrowserFromWindow( Window( _wndRef ) )
  461. If browser == _nil Then Exit Fn
  462. /*
  463.      If we are adding items then we get the number of items
  464.      from our dynamic array, if we want to delete, it is
  465.      more polite to ask the DataBrowser how many items
  466.      it has in store.
  467. */
  468. Select whatToDo
  469. Case _addItems   : numberOfItems = Fn UBound(gFiles)
  470. Case _clearItems : err = Fn GetDataBrowserItemCount( browser, _kDataBrowserNoItem, _true, _nil, numberOfItems )
  471. End Select
  472.  
  473. If numberOfItems = 0 Then Exit Fn
  474. /*
  475.      It is much more efficient to add or remove all
  476.      the items at once. To do this, we need to have
  477.      an array of itemIDs to pass onto the DataBrowser
  478.      control along with the number of itemIDs in that
  479.      array.
  480.      We must then recreate or "fake" the array filling
  481.      it with the itemIDs retrieved from our dynamic array
  482.      of itemRecords.
  483.  
  484.      We will use a temporary handle for that purpose.
  485.      The XREF@ statement will allow us to treat the
  486.      allocated memory block like an array.
  487. */
  488. Xref@ arrayOfItems(_maxInt) As DataBrowserItemID
  489.  
  490. arrayOfItems& = Fn NewHandle(numberOfItems * Sizeof(DataBrowserItemID) )
  491. If arrayOfItems = _nil Then Exit Fn
  492. /*
  493.      WARNING:
  494.      the code below will work because we have stored our
  495.      itemIDs sequentially in the DataBrowser list. This is
  496.      not a requirement, you can store any itemID value you
  497.      like (except 0) in no particular order.
  498.  
  499.      Notice that our fake array of itemIDs starts at
  500.      index 0, whereas our array of ItemRecords starts
  501.      at index 1.
  502. */
  503. For i = 1 To numberOfItems
  504. arrayOfItems(i - 1) = gFiles.itemID(i)
  505. Next
  506.  
  507. Select whatToDo
  508. Case _clearItems : err = Fn RemoveDataBrowserItems ( browser,_kDataBrowserNoItem, numberOfItems, @arrayOfItems(0) , _kDataBrowserItemNoProperty )
  509. Case _addItems   : err = Fn AddDataBrowserItems( browser, _kDataBrowserNoItem, numberOfItems, @arrayOfItems(0), _kDataBrowserItemNoProperty )
  510. End Select
  511.  
  512. DisposeHandle(arrayOfItems&)// Get rid of the memory used by our temporary handle
  513.  
  514. err = Fn SetDataBrowserScrollPosition ( browser, 0, 0 )// reset the scroll bar position
  515.  
  516. End Fn
  517.  
  518.  
  519. '~-------
  520. '~DataBrowser Installing
  521. '~';
  522. /*
  523.      This function creates the DataBrowser. It will
  524.      size the DataBrowser control to match the content
  525.      area of the window, then remove the automatic
  526.      focus ring of the DataBrowser.
  527. */
  528. Clear Local Fn CreateDataBrowser( wRef As WindowRef )
  529. '~'9
  530.  
  531. Dim As Rect         r
  532. Dim As ControlRef @ browser
  533. Dim As Boolean    @ frameAndFocus
  534.  
  535. Long If Fn GetWindowBounds( wRef, _kWindowContentRgn, r ) = _noErr
  536. OffsetRect( r, -r.left, -r.top )
  537. Long If Fn CreateDataBrowserControl( wRef, r, _kDataBrowserListView, browser ) = _noErr
  538. // Turn off DB's focus frame
  539. Long If Fn SetControlData( browser, _kControlNoPart, _kControlDataBrowserIncludesFrameAndFocusTag, Sizeof(frameAndFocus), frameAndFocus )
  540. End If
  541. End If
  542. End If
  543.  
  544. End Fn = browser
  545.  
  546.  
  547. /*
  548.      The two functions below are supposed to simplify
  549.      the code, allowing to avoid cumbersome statements
  550. */
  551. '~'1
  552. /*
  553.      After creating the DataBrowser, you need to configure it.
  554.      That is to say to define columns and their properties.
  555.      Here are the column property types you can use:
  556.  
  557.           constant names                 cell's contents are set with
  558.      _kDataBrowserCustomType        No associated data (must use custom callbacks)
  559.      _kDataBrowserIconType          IconRef, IconTransformType, RGBColor 
  560.      _kDataBrowserTextType          CFStringRef
  561.      _kDataBrowserDateTimeType      DateTime or LongDateTime
  562.      _kDataBrowserSliderType        Min, Max, Value
  563.      _kDataBrowserCheckboxType      ThemeButtonValue
  564.      _kDataBrowserProgressBarType   Min, Max, Value
  565.      _kDataBrowserRelevanceRankType Min, Max, Value
  566.      _kDataBrowserPopupMenuType     MenuRef, Value
  567.      _kDataBrowserIconAndTextType   IconRef, CFStringRef, etc 
  568.  
  569. */
  570. Clear Local Mode
  571. Local Fn SetupColumn(        column As .DataBrowserListViewColumnDesc, ┬
  572.                         columnID As UInt32, ┬
  573.                   columnProperty As DataBrowserPropertyType, ┬
  574.                      columnTitle As Str255, ┬
  575.                      columnFlags As DataBrowserPropertyFlags, ┬
  576.                    headerContent As SInt16, ┬
  577.                         minWidth As UInt16, ┬
  578.                         maxWidth As UInt16 )
  579. '~'1
  580.  
  581. column.propertyDesc.propertyID    = columnID
  582. column.propertyDesc.propertyType  = columnProperty
  583. column.propertyDesc.propertyFlags = columnFlags
  584.  
  585. column.headerBtnDesc.btnContentInfo.contentType = headerContent
  586. column.headerBtnDesc.minimumWidth               = minWidth
  587. column.headerBtnDesc.maximumWidth               = maxWidth
  588. column.headerBtnDesc.titleString = Fn CFStringCreateWithPascalString( Fn CFAllocatorGetDefault, columnTitle, _kCFStringEncodingMacRoman )
  589.  
  590. End Fn
  591.  
  592. '~'9
  593. /*
  594.      SetupColumnHeaderStyle( column, font, size, face, mode,just )
  595.  
  596.      column     : a column descriptor
  597.  
  598.      font       : font ID used in the header button or the old contants:
  599.                     _sysfont    _london       _times
  600.                     _applfont   _athens       _helvetica
  601.                     _newyork    _sanfran      _courier
  602.                     _geneva     _toronto      _symbol
  603.                     _monaco     _cairo        _mobile
  604.                     _venice     _losangeles   _apfontid
  605.  
  606.      size      : font size in pixels
  607.  
  608.      face      : font style. Use the following constants:
  609.                     _boldBit%    _ulineBit%    _shadowBit%     
  610.                     _italicBit%  _outlineBit%  _condenseBit%
  611.                       
  612.      mode      : transfer mode. Try:
  613.                     _srcCopy       _notSrcCopy  _patCopy  _notPatCopy
  614.                     _srcOr         _notSrcOr    _patOr    _notPatOr
  615.                     _srcXor        _notSrcXor   _patXor   _notPatXor
  616.                     _srcBic        _notSrcBic   _patBic   _notPatBic                                 
  617.                     _hilite        _blend              
  618.                     _addPin        _addOver
  619.                     _subPin        _addMax
  620.                     _adMax         _subOver
  621.                     _adMin         _ditherCopy
  622.                     _transparent   _grayishTextOr
  623.                     _hilitetransfermode
  624.  
  625.      just     : text justification. Use:
  626.                     _teJustLeft     _teFlushDefault
  627.                     _teJustCenter   _teCenter
  628.                     _teJustRight    _teFlushRight
  629.                     _teForceLeft    _teFlushLeft
  630. */
  631.  
  632. Clear Local Mode
  633. Local Fn SetupColumnHeaderStyle( column As ^DataBrowserListViewColumnDesc, ┬
  634.                                font As Short, ┬
  635.                                size As Short, ┬
  636.                                face As Short, ┬
  637.                                mode As Short, ┬
  638.                                just As Short )
  639. '~'1
  640. Dim colStyle As ControlFontStyleRec
  641.  
  642. colStyle = column.headerBtnDesc.btnFontStyle
  643. If font Then colStyle.flags = colStyle.flags Or _kControlUseFontMask : colStyle.font  = font
  644. If size Then colStyle.flags = colStyle.flags Or _kControlUseSizeMask : colStyle.size  = size
  645. If face Then colStyle.flags = colStyle.flags Or _kControlUseFaceMask : colStyle.style = face
  646. If mode Then colStyle.flags = colStyle.flags Or _kControlUseModeMask : colStyle.Mode  = mode
  647. If just Then colStyle.flags = colStyle.flags Or _kControlUseJustMask : colStyle.just  = just
  648. call BlockMoveData( @colStyle, @column.headerBtnDesc.btnFontStyle, Sizeof(ControlFontStyleRec) )
  649.  
  650. End Fn
  651.  
  652. /*
  653.      This function will add a single column in the DataBrowser control
  654. */
  655. Clear Local Fn ConfigureDataBrowser( browser As ControlRef )
  656. '~'9
  657. Dim As OSStatus                       err
  658. Dim As DataBrowserListViewColumnDesc  col
  659. Dim As DataBrowserViewStyle         @ viewStyle
  660.  
  661. err = Fn GetDataBrowserViewStyle( browser, viewStyle )
  662.  
  663. Select viewStyle
  664.  
  665. Case _kDataBrowserListView:
  666.  
  667. col.headerBtnDesc.titleOffset = 0
  668. col.headerBtnDesc.version     = _kDataBrowserListViewLatestHeaderDesc
  669.  
  670. // ------- Add the name & icon column ------- 
  671. /*
  672.      Custom function for easy setup
  673.  
  674.      FN SetupColumn( columnDescriptor,┬
  675.                              columnID, ┬
  676.                        columnProperty, ┬
  677.                           columnTitle, ┬
  678.                           columnFlags, ┬
  679.                         headerContent, ┬
  680.                              minWidth, ┬
  681.                              maxWidth )
  682. */
  683.  
  684. Fn SetupColumn(          col, ┬
  685.                _fileColumnID, ┬
  686. _kDataBrowserIconAndTextType, ┬
  687.                        "Name",┬
  688. _kDataBrowserListViewSelectionColumn_kDataBrowserListViewDefaultColumnFlags, ┬
  689.     _kControlContentTextOnly, ┬
  690.                       0 ,280 )
  691. /*
  692.      Custom function for easy setup
  693.  
  694.      FN SetupColumnHeaderStyle( columnDescriptor, fontID, textSize, textFace, textMode,justification )
  695. */
  696.  
  697. Fn SetupColumnHeaderStyle( col, 0, 0, 0, 0, _teFlushDefault )
  698. err = Fn AddDataBrowserListViewColumn( browser, col, _kDataBrowserListViewAppendColumn )
  699.  
  700. Case _kDataBrowserColumnView:
  701.  
  702. End Select
  703.  
  704. End Fn
  705.  
  706.  
  707. '~';
  708. /*
  709.      This function sets the callback procedure that the
  710.      DataBrowser will use to communicate with the program.
  711.      There is a bunch of callback routines available
  712.      for customization of the DataBrowser. Here, we use the
  713.      only one which is required to display data.
  714. */
  715. Clear Local Fn InstallDataBrowserCallbacks( browser As ControlRef )
  716. '~'9
  717.  
  718. Dim As OSStatus               err
  719. Dim As DataBrowserCallbacks @ myCallbacks
  720.  
  721. myCallbacks.version = _kDataBrowserLatestCallbacks//Use latest layout and callback signatures
  722.  
  723. err = Fn InitDataBrowserCallbacks( myCallbacks )
  724. myCallbacks.u.itemDataCallback  = Fn NewDataBrowserItemDataUPP ( [Proc "GetSetItemDataProc"  + _FBprocToProcPtrOffset] )
  725. err = Fn SetDataBrowserCallbacks( browser, myCallbacks )
  726.  
  727. End Fn
  728.  
  729.  
  730. '~';
  731. /*
  732.      This function will resize the DataBrowser when needed,
  733.      for example, when the window is resized.
  734. */
  735. Clear Local Fn RefreshDataBrowser( wNum As Long )
  736. '~'9
  737.  
  738. Dim As Rect         r
  739. Dim As ControlRef   browser
  740. Dim As WindowRef  @ wRef
  741.  
  742. Get Window wNum, wRef// retrieve the WindowRef from the FB Window number
  743. Long If wRef
  744. Long If Fn GetWindowBounds( wRef, _kWindowContentRgn, r ) = _noErr
  745. browser = Fn GetDataBrowserFromWindow( wRef )
  746. Long If browser
  747. SizeControl( browser, r.right - r.left, r.bottom - r.top)
  748. End If
  749. End If
  750. End If
  751.  
  752. End Fn
  753.  
  754.  
  755. '~';
  756. '~----
  757. '~Event Handling
  758. '~'1
  759. /*
  760.     This function is called via our cheap menu.
  761. */
  762. Clear Local Fn doOpenFolder 
  763. '~'9
  764.  
  765. Dim As Int    err
  766. Dim As FSSpec fSpec
  767. Dim As Str255 name 
  768.  
  769. Long If Len( Files$( _FSSpecFolder, "Choose a folder",,fSpec ) )// select folder dialog
  770. Fn AddOrClearDataBrowserItems( _clearItems )// not cancelled, so clear the current DataBrowser's items
  771. Kill Dynamic gFiles// dispose of the current dynamic array
  772. Fn CollectFileItems( fSpec )// collect files and folders
  773. Compress Dynamic gFiles// optimize memory
  774. Fn AddOrClearDataBrowserItems( _addItems )// create the DataBrowser items with the grabbed info
  775. err = Usr FSGetFolderName( fSpec, name )// retrieve the folder name since folder FSSpecs have an empty name
  776. Window _mainWnd, name// update window title
  777. End If
  778.  
  779. End Fn
  780.  
  781.  
  782. /*
  783.      No risk of indigestion with that menu
  784. */
  785. Local Fn doMenu
  786. '~'9
  787.  
  788. Dim As Short menuID, itemID
  789.  
  790. menuID = Menu( _menuID )
  791. itemID = Menu( _ItemID )
  792.  
  793. Select menuID
  794. Case _menuFile
  795. Select itemID
  796. Case _itemOpenFolder : Fn doOpenFolder
  797. Case _itemQuit       : End
  798. End Select
  799. End Select
  800.  
  801. Menu
  802.  
  803. End Fn
  804.  
  805.  
  806. /*
  807.      Minimalist dialog handler
  808. */
  809. Local Fn doDialog
  810. '~'9
  811. Dim As Long act, ref
  812.  
  813. act = Dialog(0)
  814. ref = Dialog(act)
  815.  
  816. Select act
  817. Case _wndZoomIn, _wndZoomOut,_wndResized
  818. Fn RefreshDataBrowser( ref )
  819. Case _wndClose : End
  820. End Select
  821.  
  822. End Fn
  823.  
  824. '~';
  825. '~------
  826. '~Program starts here
  827. '~';
  828. /*
  829.      This function installs our cheap menu, a window
  830.      and a DataBrowser control in that window.
  831.      It runs the main event loop too.
  832. */
  833. Clear Local Fn StartProgram
  834. '~'9
  835. Dim As OSStatus        err
  836. Dim As Rect            r
  837. Dim As WindowRef     @ wRef
  838. Dim As ControlRef    @ browser
  839.  
  840. // Setup a menu
  841. Menu _menuFile, 0              , _enable, "File"
  842. Menu _menuFile, _itemOpenFolder, _enable, "Open Folder/O"
  843. Menu _menuFile, _itemQuit      , _enable, "Quit/Q"
  844.  
  845. // Setup a window
  846. SetRect( r, 100, 100, 600, 400 )
  847. Appearance Window - _mainWnd, "Simple DataBrowser", @r ,_kDocumentWindowClass, ┬
  848.                     _kWindowInWindowMenuAttribute _kWindowStandardDocumentAttributes
  849.                                                                                                
  850. wRef = Window( _wndRef )// Get the WindowRef of that window
  851. err  = Fn SetAutomaticControlDragTrackingEnabledForWindow( wRef, _true )
  852.  
  853. // Create the DataBrowser control
  854. browser = Fn CreateDataBrowser( wRef )
  855. Long If browser
  856. Fn InstallDataBrowserCallbacks( browser )// Install the callback routines
  857. Fn ConfigureDataBrowser( browser )// Configure the DataBrowser
  858. err = Fn SetKeyboardFocus( wRef, browser, _kControlDataBrowserPart )// Set the keyboard focus
  859. err = Fn SetWindowProperty( wRef, _myCreator, _myDataBrowser, Sizeof(browser), browser )// Store our custom DataBrowser ID as a window property
  860. End If
  861.  
  862. Window _mainWnd// Make the window visible
  863.  
  864. On Menu   Fn doMenu
  865. On Dialog Fn doDialog
  866.  
  867. Do
  868. Handleevents
  869. Until _nil
  870.  
  871. End Fn
  872.  
  873. // The start
  874. Fn StartProgram
  875.  
  876. '~---
  877. '~Applications Proc
  878. /*
  879.      Entry point for the callback procedure
  880. */
  881. #If Def _FBUseDebugger
  882. Troff
  883. #Endif
  884.  
  885. Goto "skip procs"
  886.  
  887. "GetSetItemDataProc"
  888. Enterproc Fn GetSetItemDataProc( browser As ControlRef, itemID As DataBrowserItemID, prop As DataBrowserPropertyID, itemData As DataBrowserItemDataRef, changeValue As Boolean ) = OSStatus
  889. Exitproc = Fn MyGetSetItemData( browser, itemID, prop, itemData, changeValue )
  890.  
  891. "skip procs"
  892.  
  893. #If Def _FBUseDebugger
  894. Tron
  895. #Endif
  896.  
  897.